/*
 * @Author: hanyuanjiao
 * @Date: 2025-07-21 06:52:28
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2025-08-19 14:51:45
 * @Description: 指令的具体执行方法类
 */
#include "instr.h"
#include "simu8051.h"
#include "tools.h"
#include "mem.h"
#include <stdio.h>
#include <string.h>

#define TEST 1
extern simu8051_t simu;

void show_disa(instr_t *instr)
{
    const instr_info_t *info = instr->info;
    printf("C:0x%04x\t", simu8051_pc());
#if TEST
    printf("bytes:%2d\tcycle: %2d\t", info->bytes, info->cycles);
#endif
    if (info->bytes == 1)
    {
        printf("%02x\t%s %s", instr->opcode, info->disa_opcode, info->disa0);
        if (strlen(info->disa1))
        {
            printf(",%s\n", info->disa1);
        }
        else
        {
            printf("\n");
        }
    }
    else if (info->bytes == 2)
    {
        printf("%02x%02x\t%s %s", instr->opcode, instr->op0, info->disa_opcode, info->disa0);
        if (strlen(info->disa1))
        {
            printf(",%s\n", info->disa1);
        }
        else
        {
            printf("\n");
        }
    }
    else
    {
        printf("%02x%02x%02x\t%s %s,%s\n",
               instr->opcode,
               instr->op0,
               instr->op1,
               info->disa_opcode,
               info->disa0,
               info->disa1);
    }
}
/**
 * @description: 获取操作数,取的是代码级,而非二进制码级别,比如mov r0,#0x12, op_num=1指的是12,op_num=0指的是r0
 * @param {instr_t} *instr
 * @param {int} op_num 操作数的序号
 * @return {*}
 */
static uint8_t get_op(instr_t *instr, int op_num)
{
    const instr_info_t *info = instr->info;
    if (op_num == 0)
    {
        switch (info->op0_mode)
        {
        case OTYPE_IMM8:
        case OTYPE_DIRECT:
        case OTYPE_BIT:
            return instr->op0;
        default:
            return 0;
        }
    }
    else
    {
        //对于mov direct,#imm8或者mov direct,direct,若op_num==1,绝对返回op1,op_num==0由前项处理
        //对于mov direct,A若op_num==1,也只能选择返回op0,因为不存在op1
        return (info->bytes > 2) ? instr->op1 : instr->op0;
    }
}
static int get_rs(void)
{
    return (simu8051_read(MEM_TYPE_SFR, SFR_PSW) & 0x18) >> 3;
}
/**
 * @description: 依据操作数与其对应的存储类型,从存储中获取数据
 * @param {instr_t} *instr
 * @param {int} op_num 操作数编号: 0->op0,1->op1,针对的是instr_info_t中的序号,而不是instr_t
 * @param {mem_type_t} mem_type 存储器类型
 * @return {value} 返回操作数
 */
static uint16_t read_op(instr_t *instr, int op_num, mem_type_t mem_type)
{
    const instr_info_t *info    = instr->info;
    op_type_t           op_mode = op_num ? info->op1_mode : info->op0_mode;
    //取得操作数的值
    uint8_t op = get_op(instr, op_num);
    switch (op_mode)
    {
    case OTYPE_NONE:
        break;
    case OTYPE_Rn:
    {
        // opcode的低3位指定R0~R7
        int reg = instr->opcode & 0x7;
        // SR1:SR0=00时,R0~R7=0x00~0x07
        return simu.mem.iram[reg + get_rs() * 0x08];
    }

    case OTYPE_IMM8:
        return op;
    case OTYPE_ACC:
        return simu8051_read(MEM_TYPE_SFR, SFR_ACC);
    case OTYPE_B:
        return simu8051_read(MEM_TYPE_SFR, SFR_B);
    case OTYPE_DIRECT:
        return simu8051_read(MEM_TYPE_IRAM, op);
    case OTYPE_DPTR:
        return simu8051_read(MEM_TYPE_SFR, SFR_DPH) << 8 | simu8051_read(MEM_TYPE_SFR, SFR_DPL);
    case OTYPE_IMM16:
        return instr->op0 << 8 | instr->op1;
    case OTYPE_INDIRECT_R0_1:
    {
        uint8_t addr = simu8051_read(MEM_TYPE_IRAM, (instr->opcode & 0x1) + get_rs() * 8);
        return simu8051_read(mem_type, addr);
    }
    case OTYPE_C:
        return simu8051_read(MEM_TYPE_BIT, SFR_PSW_CY);
    case OTYPE_BIT:
        return simu8051_read(MEM_TYPE_BIT, op);
    case OTYPE_INV_BIT:
        return ~simu8051_read(MEM_TYPE_BIT, op);
    case OTYPE_INDIRECT_ACC_DPTR:
    {
        uint16_t addr = simu8051_read(MEM_TYPE_SFR, SFR_DPH) << 8 | simu8051_read(MEM_TYPE_SFR, SFR_DPL);
        uint8_t  acc  = simu8051_read(MEM_TYPE_SFR, SFR_ACC);
        return simu8051_read(mem_type, addr + acc);
    }
    case OTYPE_INDIRECT_ACC_PC:
    {
        uint16_t pc  = simu8051_pc() + 1;
        uint8_t  acc = simu8051_read(MEM_TYPE_SFR, SFR_ACC);
        return simu8051_read(mem_type, pc + acc);
    }
    case OTYPE_INDIRECT_DPTR:
    {
        uint16_t addr = simu8051_read(MEM_TYPE_SFR, SFR_DPH) << 8 | simu8051_read(MEM_TYPE_SFR, SFR_DPL);
        return simu8051_read(mem_type, addr);
    }
    case OTYPE_INDIRECT_SP:
    {
        uint16_t addr = simu8051_read(MEM_TYPE_SFR, SFR_SP);
        return simu8051_read(mem_type, addr);
    }
    }
    return 0;
}
/**
 * @description: 写操作数
 * @param {instr_t} *instr
 * @param {uint16_t} data
 * @param {int} op_num
 * @param {mem_type_t} mem_type
 * @return {*}
 */
static void write_op(instr_t *instr, uint16_t data, int op_num, mem_type_t mem_type)
{
    const instr_info_t *info    = instr->info;
    op_type_t           op_mode = op_num ? info->op1_mode : info->op0_mode;
    uint8_t             op      = get_op(instr, op_num);
    switch (op_mode)
    {
    case OTYPE_Rn:
    {
        //与Rn有关的操作码,一般低3位放置Rn索引
        int reg                              = instr->opcode & 0x7;
        simu.mem.iram[reg + get_rs() * 0x08] = (uint8_t)data;
        break;
    }

    case OTYPE_IMM8:
    case OTYPE_IMM16:
        break;
    case OTYPE_ACC:
        simu8051_write(MEM_TYPE_SFR, SFR_ACC, (uint8_t)data);
        break;
    case OTYPE_B:
        simu8051_write(MEM_TYPE_SFR, SFR_B, (uint8_t)data);
        break;
    case OTYPE_DIRECT:
        simu8051_write(MEM_TYPE_IRAM, op, (uint8_t)data);
        break;
    case OTYPE_DPTR:
        simu8051_write(MEM_TYPE_SFR, SFR_DPH, data >> 8);
        simu8051_write(MEM_TYPE_SFR, SFR_DPL, (uint8_t)data);
        break;
    case OTYPE_INDIRECT_R0_1:
    {
        //读取R0或R1中的值
        uint8_t addr = simu8051_read(MEM_TYPE_IRAM, (instr->opcode & 0x1) + get_rs() * 8);
        simu8051_write(mem_type, addr, (uint8_t)data);
        break;
    }
    case OTYPE_C:
        simu8051_write(MEM_TYPE_BIT, SFR_PSW_CY, (uint8_t)data);
        break;
    case OTYPE_BIT:
        simu8051_write(MEM_TYPE_BIT, op, (uint8_t)data);
        break;
    case OTYPE_INDIRECT_DPTR:
    {
        uint16_t addr = simu8051_read(MEM_TYPE_SFR, SFR_DPH) << 8 | simu8051_read(MEM_TYPE_SFR, SFR_DPL);
        simu8051_write(mem_type, addr, data);
        break;
    }
    case OTYPE_INDIRECT_SP:
    {
        uint16_t addr = simu8051_read(MEM_TYPE_SFR, SFR_SP);
        simu8051_write(mem_type, addr, (uint8_t)data);
    }
    default:
        break;
    }
}
/**
 * @description: 通用的指令操作,仅包含增加pc与cycle
 * @param {instr_t} *instr
 * @return {*}
 */
static void instr_common(instr_t *instr)
{
    simu.pc += instr->info->bytes;
    simu.cycles += instr->info->cycles;
}

void do_nop(instr_t *instr)
{
    instr_common(instr);
}

void do_mov(instr_t *instr)
{
    // const instr_info_t *info = instr->info;
    //针对mov direct,direct的特殊处理,因为芯片处理方向与汇编得到的机器码的方向相反,一致改为op1->op0(汇编语言层级)
    if (instr->opcode == 0x85)
    {
        uint16_t src_data = read_op(instr, 0, MEM_TYPE_IRAM);
        write_op(instr, src_data, 1, MEM_TYPE_IRAM);
    }
    else
    {
        // 1指的是mov R0,#0x12 中的0x12
        // 1指的是mov direct,#imm8 中的imm8
        uint16_t src_data = read_op(instr, 1, MEM_TYPE_IRAM);
        write_op(instr, src_data, 0, MEM_TYPE_IRAM);
    }
    instr_common(instr);
}

void do_movc(instr_t *instr)
{
    uint16_t src_data = read_op(instr, 1, MEM_TYPE_CODE);
    write_op(instr, src_data, 0, MEM_TYPE_CODE);
    instr_common(instr);
}
void do_movx(instr_t *instr)
{
    //这里的MEM_TYPE_XRAM实际上不一定用到了,因为先采用的是info中的op_mode
    //对于movx @dptr,A与movx @Ri,A没有用到
    //对于movx A,@dptr与movx A,@Ri用到了
    uint16_t src_data = read_op(instr, 1, MEM_TYPE_XRAM);
    //这里的MEM_TYPE_XRAM实际上不一定用到了
    //对于movx @dptr,A与movx @Ri,A有用到
    //对于movx A,@dptr与movx A,@Ri没有用到了
    write_op(instr, src_data, 0, MEM_TYPE_XRAM);
    instr_common(instr);
}
void do_push(instr_t *instr)
{
    //读取操作数
    uint16_t src_data = read_op(instr, 0, MEM_TYPE_IRAM);
    //处理sp,压栈
    simu8051_write(MEM_TYPE_SFR, SFR_SP, simu8051_sp() + 1);
    simu8051_write(MEM_TYPE_IRAM, simu8051_sp(), src_data);
    instr_common(instr);
}
void do_pop(instr_t *instr)
{
    //读取栈中的数据
    uint8_t src_data = simu8051_read(MEM_TYPE_IRAM, simu8051_sp());
    //弹出,处理sp
    write_op(instr, src_data, 0, MEM_TYPE_IRAM);
    simu8051_write(MEM_TYPE_SFR, SFR_SP, simu8051_sp() - 1);
    instr_common(instr);
}
void do_swap(instr_t *instr)
{
    uint8_t data = read_op(instr, 0, MEM_TYPE_IRAM);
    data         = (data << 4) | (data >> 4);
    write_op(instr, data, 0, MEM_TYPE_IRAM);
    instr_common(instr);
}
void do_xch(instr_t *instr)
{
    uint16_t src_data  = read_op(instr, 1, MEM_TYPE_IRAM);
    uint16_t dest_data = read_op(instr, 0, MEM_TYPE_IRAM);
    if (instr->opcode & (1 << 4))
    {
        //处理xchd的情况,仅仅交换低4位
        uint8_t tmp = src_data;
        src_data    = (src_data & ~0xF) | (dest_data & 0xF);
        dest_data   = (dest_data & ~0xF) | (tmp & 0xF);
    }
    else
    {
        uint16_t tmp = src_data;
        src_data     = dest_data;
        dest_data    = tmp;
    }
    write_op(instr, src_data, 1, MEM_TYPE_IRAM);
    write_op(instr, dest_data, 0, MEM_TYPE_IRAM);
    instr_common(instr);
}
void do_anl(instr_t *instr)
{
    uint16_t src_data  = read_op(instr, 1, MEM_TYPE_IRAM);
    uint16_t dest_data = read_op(instr, 0, MEM_TYPE_IRAM);
    dest_data          = src_data & dest_data;
    write_op(instr, dest_data, 0, MEM_TYPE_IRAM);
    instr_common(instr);
}
void do_orl(instr_t *instr)
{
    uint16_t src_data  = read_op(instr, 1, MEM_TYPE_IRAM);
    uint16_t dest_data = read_op(instr, 0, MEM_TYPE_IRAM);
    dest_data          = src_data | dest_data;
    write_op(instr, dest_data, 0, MEM_TYPE_IRAM);
    instr_common(instr);
}
void do_xrl(instr_t *instr)
{
    uint16_t src_data  = read_op(instr, 1, MEM_TYPE_IRAM);
    uint16_t dest_data = read_op(instr, 0, MEM_TYPE_IRAM);
    dest_data          = src_data ^ dest_data;
    write_op(instr, dest_data, 0, MEM_TYPE_IRAM);
    instr_common(instr);
}
void do_clr(instr_t *instr)
{
    write_op(instr, 0, 0, MEM_TYPE_IRAM);
    instr_common(instr);
}
void do_setb(instr_t *instr)
{
    write_op(instr, 1, 0, MEM_TYPE_IRAM);
    instr_common(instr);
}
void do_cpl(instr_t *instr)
{
    uint16_t src_data = read_op(instr, 0, MEM_TYPE_IRAM);
    write_op(instr, ~src_data, 0, MEM_TYPE_IRAM);
    instr_common(instr);
}
void do_rl(instr_t *instr)
{
    uint8_t acc = read_op(instr, 0, MEM_TYPE_IRAM);
    if (instr->opcode & (1 << 4))
    {
        // case: RLC A
        uint8_t cy = simu8051_read(MEM_TYPE_BIT, SFR_PSW_CY);
        simu8051_write(MEM_TYPE_BIT, SFR_PSW_CY, acc >> 7);
        acc = (acc << 1) | cy;
    }
    else
    {
        acc = (acc << 1) | (acc >> 7);
    }
    write_op(instr, acc, 0, MEM_TYPE_IRAM);
    instr_common(instr);
}
void do_rr(instr_t *instr)
{
    uint8_t acc = read_op(instr, 0, MEM_TYPE_IRAM);
    if (instr->opcode & (1 << 4))
    {
        // case: RRC A
        uint8_t cy = simu8051_read(MEM_TYPE_BIT, SFR_PSW_CY);
        simu8051_write(MEM_TYPE_BIT, SFR_PSW_CY, (acc & 0x01) ? 1 : 0);
        acc = (acc >> 1) | (cy << 7);
    }
    else
    {
        acc = (acc >> 1) | (acc << 7);
    }
    write_op(instr, acc, 0, MEM_TYPE_IRAM);
    instr_common(instr);
}
void do_add(instr_t *instr)
{
    uint8_t  acc = simu8051_read(MEM_TYPE_SFR, SFR_ACC);
    uint16_t src = read_op(instr, 1, MEM_TYPE_IRAM);
    uint16_t res = acc + src;
    if (instr->opcode & (1 << 4))
    {
        //处理addc
        uint8_t cy = simu8051_read(MEM_TYPE_BIT, SFR_PSW_CY);
        res += cy;
    }
    write_op(instr, res, 0, MEM_TYPE_IRAM);
    // set ac,cy,ov
    int bit3_c = ((acc & 0x0F) + (src & 0x0F)) & 0x10 ? 1 : 0;
    int bit6_c = ((acc & 0x7F) + (src & 0x7F)) & 0x80 ? 1 : 0;
    int bit7_c = res & 0x100 ? 1 : 0;
    // set ac,bit3->bit4发生进位,用于BCD码
    simu8051_write(MEM_TYPE_BIT, SFR_PSW_AC, bit3_c);
    // set cy
    simu8051_write(MEM_TYPE_BIT, SFR_PSW_CY, bit7_c);
    // set OV
    simu8051_write(MEM_TYPE_BIT, SFR_PSW_OV, bit6_c ^ bit7_c);
    instr_common(instr);
}
void do_subb(instr_t *instr)
{
    uint8_t  acc = simu8051_read(MEM_TYPE_SFR, SFR_ACC);
    uint16_t src = read_op(instr, 1, MEM_TYPE_IRAM);
    uint8_t  cy  = simu8051_read(MEM_TYPE_BIT, SFR_PSW_CY);
    uint16_t res = acc - src - cy;
    write_op(instr, res, 0, MEM_TYPE_IRAM);
    // set ac,cy,ov
    int bit3_c = ((acc & 0x0F) - (src & 0x0F) - cy) & 0x10 ? 1 : 0;
    int bit6_c = ((acc & 0x7F) - (src & 0x7F) - cy) & 0x80 ? 1 : 0;
    int bit7_c = res & 0x100 ? 1 : 0;
    // set ac,bit3->bit4发生进位,用于BCD码
    simu8051_write(MEM_TYPE_BIT, SFR_PSW_AC, bit3_c);
    // set cy
    simu8051_write(MEM_TYPE_BIT, SFR_PSW_CY, bit7_c);
    // set OV
    simu8051_write(MEM_TYPE_BIT, SFR_PSW_OV, bit6_c ^ bit7_c);
    instr_common(instr);
}
void do_mul(instr_t *instr)
{
    uint8_t  acc = simu8051_read(MEM_TYPE_SFR, SFR_ACC);
    uint8_t  b   = simu8051_read(MEM_TYPE_SFR, SFR_B);
    uint16_t res = (uint16_t)acc * b;
    simu8051_write(MEM_TYPE_IRAM, SFR_ACC, res & 0xFF);
    simu8051_write(MEM_TYPE_IRAM, SFR_B, res >> 8);
    simu8051_write(MEM_TYPE_BIT, SFR_PSW_OV, res > 0xFF ? 1 : 0);
    simu8051_write(MEM_TYPE_BIT, SFR_PSW_CY, 0);
    instr_common(instr);
}
void do_div(instr_t *instr)
{
    uint8_t acc = simu8051_read(MEM_TYPE_SFR, SFR_ACC);
    uint8_t b   = simu8051_read(MEM_TYPE_SFR, SFR_B);
    if (b)
    {
        uint8_t quotient  = acc / b;
        uint8_t remainder = acc % b;
        simu8051_write(MEM_TYPE_SFR, SFR_ACC, quotient);
        simu8051_write(MEM_TYPE_SFR, SFR_B, remainder);
        simu8051_write(MEM_TYPE_BIT, SFR_PSW_OV, 0);
    }
    else
    {
        simu8051_write(MEM_TYPE_BIT, SFR_PSW_OV, 1);
    }
    simu8051_write(MEM_TYPE_BIT, SFR_PSW_CY, 0);
    instr_common(instr);
}
void do_inc(instr_t *instr)
{
    uint16_t src = read_op(instr, 0, MEM_TYPE_IRAM);
    write_op(instr, src + 1, 0, MEM_TYPE_IRAM);
    instr_common(instr);
}
void do_dec(instr_t *instr)
{
    uint16_t src = read_op(instr, 0, MEM_TYPE_IRAM);
    write_op(instr, src - 1, 0, MEM_TYPE_IRAM);
    instr_common(instr);
}
void do_da(instr_t *instr)
{
    uint16_t acc = simu8051_read(MEM_TYPE_SFR, SFR_ACC);
    uint8_t  ac  = simu8051_read(MEM_TYPE_BIT, SFR_PSW_AC);
    uint8_t  cy  = simu8051_read(MEM_TYPE_BIT, SFR_PSW_CY);
    if ((acc & 0xf) > 9 || ac)
    {
        acc += 6;
    }
    if (acc >= 0x100)
    {
        cy = 1;
    }
    if ((acc & 0xf0) > 0x90 || cy)
    {
        acc += 0x60;
    }
    if (acc >= 0x100)
    {
        cy = 1;
    }
    simu8051_write(MEM_TYPE_SFR, SFR_ACC, acc);
    simu8051_write(MEM_TYPE_BIT, SFR_PSW_CY, cy);
    instr_common(instr);
}
void do_acall(instr_t *instr)
{
    instr_common(instr);
    uint8_t sp = simu8051_read(MEM_TYPE_SFR, SFR_SP) + 1;
    simu8051_write(MEM_TYPE_IRAM, sp++, simu8051_pc());
    simu8051_write(MEM_TYPE_IRAM, sp, simu8051_pc() >> 8);
    simu8051_write(MEM_TYPE_SFR, SFR_SP, sp);
    simu.pc = (simu8051_pc() & 0xF800) | ((instr->opcode & 0xE0) << 3 | (instr->op0));
}
void do_lcall(instr_t *instr)
{
    instr_common(instr);
    uint8_t sp = simu8051_read(MEM_TYPE_SFR, SFR_SP) + 1;
    simu8051_write(MEM_TYPE_IRAM, sp++, simu8051_pc());
    simu8051_write(MEM_TYPE_IRAM, sp, simu8051_pc() >> 8);
    simu8051_write(MEM_TYPE_SFR, SFR_SP, sp);
    simu.pc = instr->op0 << 8 | instr->op1;
}
void do_ajmp(instr_t *instr)
{
    instr_common(instr);
    simu.pc = (simu8051_pc() & 0xF800) | ((instr->opcode & 0xE0) << 3 | (instr->op0));
}
void do_ljmp(instr_t *instr)
{
    simu.pc = instr->op0 << 8 | instr->op1;
    simu.cycles += instr->info->cycles;
}
void do_sjmp(instr_t *instr)
{
    instr_common(instr);
    uint16_t src_data = read_op(instr, 0, MEM_TYPE_IRAM);
    simu.pc += (int8_t)src_data;
}
void do_jmp_a_dptr(instr_t *instr)
{
    uint16_t addr = simu8051_read(MEM_TYPE_SFR, SFR_DPH) << 8 | simu8051_read(MEM_TYPE_SFR, SFR_DPL);
    uint8_t  acc  = simu8051_read(MEM_TYPE_SFR, SFR_ACC);
    simu.pc       = addr + acc;
    simu.cycles += instr->info->cycles;
}
void do_jb(instr_t *instr)
{
    instr_common(instr);
    uint16_t bit_ = read_op(instr, 0, MEM_TYPE_IRAM);
    int8_t   rel  = (int8_t)instr->op1;
    // jb  0x20
    // jbc 0x10
    // jnb 0x30
    if (instr->opcode == 0x30)
    {
        // jnb
        simu.pc += !bit_ ? rel : 0;
    }
    else
    {
        // jb | jbc
        simu.pc += bit_ ? rel : 0;
    }
    if (instr->opcode == 0x10 && bit_)
    {
        // jbc
        write_op(instr, 0, 0, MEM_TYPE_IRAM);
    }
}
void do_jc(instr_t *instr)
{
    instr_common(instr);
    uint8_t cy  = simu8051_read(MEM_TYPE_BIT, SFR_PSW_CY);
    int8_t  rel = (int8_t)instr->op0;
    if (instr->opcode & (1 << 4))
    {
        // jnc
        simu.pc += !cy ? rel : 0;
    }
    else
    {
        // jc
        simu.pc += cy ? rel : 0;
    }
}
void do_jz(instr_t *instr)
{
    instr_common(instr);
    uint8_t acc = simu8051_read(MEM_TYPE_SFR, SFR_ACC);
    int8_t  rel = (int8_t)instr->op0;
    //(jnz && acc) || (jz && !acc)
    if ((instr->opcode & (1 << 4)))
    {
        simu.pc += acc ? rel : 0;
    }
    else
    {
        simu.pc += !acc ? rel : 0;
    }
}
void do_cjne(instr_t *instr)
{
    instr_common(instr);
    uint16_t v0 = read_op(instr, 0, MEM_TYPE_IRAM);
    uint8_t  v1;
    switch (instr->info->op1_mode)
    {
    case OTYPE_DIRECT:
        v1 = simu8051_read(MEM_TYPE_IRAM, instr->op0);
        break;
    case OTYPE_IMM8:
        v1 = instr->op0;
        break;
    default:
        printf("unknow cjne op0 type:%d\n", instr->info->op0_mode);
        exit(-1);
    }
    simu.pc += v0 != v1 ? (int8_t)instr->op1 : 0;
    simu8051_write(MEM_TYPE_BIT, SFR_PSW_CY, v0 < v1 ? 1 : 0);
}
void do_djnz(instr_t *instr)
{
    instr_common(instr);
    uint16_t v = read_op(instr, 0, MEM_TYPE_IRAM) - 1;
    write_op(instr, v, 0, MEM_TYPE_IRAM);
    if (v)
    {
        int8_t rel = (instr->opcode & (1 << 3)) ? (int8_t)instr->op0 : (int8_t)instr->op1;
        simu.pc += rel;
    }
}
void do_ret(instr_t *instr)
{
    uint8_t sp   = simu8051_read(MEM_TYPE_SFR, SFR_SP);
    uint8_t pc_h = simu8051_read(MEM_TYPE_IRAM, sp--);
    uint8_t pc_l = simu8051_read(MEM_TYPE_IRAM, sp--);
    simu.pc      = pc_h << 8 | pc_l;
    simu8051_write(MEM_TYPE_SFR, SFR_SP, sp);
    simu.cycles += instr->info->cycles;
}
void do_reti(instr_t *instr)
{
    do_ret(instr);
    simu.in_int = 0;
}